import path from "node:path";
import { RunnerSpec, TaskHandler } from "../types";
import { resolvePath, ensureDir } from "../utils";
import { loadStructuredData, writeJsonFile } from "../../../tools/data-processor";

function extractColors(payload: any): string[] {
  const styles = payload?.globalVars?.styles;
  if (!styles || typeof styles !== "object") {
    return [];
  }
  return Object.entries(styles)
    .filter(([key]) => key.toLowerCase().includes("color"))
    .map(([key, value]) => `${key}:${JSON.stringify(value)}`)
    .slice(0, 50);
}

function extractTypography(payload: any): string[] {
  const nodes = Array.isArray(payload?.nodes) ? payload.nodes : [];
  return nodes
    .filter((node: any) => node.textStyle)
    .map((node: any) => `${node.name ?? node.id}:${JSON.stringify(node.textStyle)}`)
    .slice(0, 50);
}

function extractSpacing(payload: any): number[] {
  const nodes = Array.isArray(payload?.nodes) ? payload.nodes : [];
  const spacingValues = new Set<number>();
  for (const node of nodes) {
    if (typeof node.layout?.padding === "number") {
      spacingValues.add(node.layout.padding);
    }
    if (typeof node.layout?.gap === "number") {
      spacingValues.add(node.layout.gap);
    }
  }
  return Array.from(spacingValues).slice(0, 50);
}

export const tokensExtractTask: TaskHandler = async (spec) => {
  if (!spec.figma) {
    throw new Error("spec.figma is required for tokens.extract");
  }

  const minRelative = spec.figma.minPath ?? spec.output?.min ?? path.join(spec.output?.dir ?? "figma", "figma-main.min.yaml");
  const tokensRelative = spec.figma.tokensPath ?? spec.output?.tokens ?? path.join(spec.output?.dir ?? "figma", "tokens.json");
  const minPath = resolvePath(minRelative);
  const tokensPath = resolvePath(tokensRelative);
  await ensureDir(path.dirname(tokensPath));

  const data = await loadStructuredData(minPath);
  const payload = data ?? {};
  const tokens = {
    colors: extractColors(payload),
    typography: extractTypography(payload),
    spacing: extractSpacing(payload),
  };

  await writeJsonFile(tokensPath, tokens);

  return {
    summary: `Extracted ${tokens.colors.length + tokens.typography.length} tokens`,
    outputPaths: { tokens: tokensRelative },
  };
};
